import React, { useEffect, useRef, useState, ElementRef, forwardRef, useImperativeHandle } from 'react';
import { cloneDeep } from 'lodash';
import { Form, Input } from '@block/plug';
import { CollapseList } from '@src/components';
import { getUUid } from '@src/utils';
import { AuditFindingItem } from '..';
import { NORMAL_MAX_LENGTH, PROBLEM_LIST_MAX } from '../../constant';
import { AuditFindingsGroup } from '../../types';
import './AuditFindingGroup.scss';

interface Props extends DefaultToEditItem {
  value?: AuditFindingsGroup[];
  onChange?: (val: AuditFindingsGroup[]) => void;
  mode?: Mode;
  riskGradeList: SelectOption[];
}

interface Handle {
  /** 表单校验 */
  onValidate: () => boolean;
}

/**
 * 审计发现组
 */
const AuditFindingGroup = forwardRef<Handle, Props>((props, ref) => {
  const { value, onChange, mode, riskGradeList = [] } = props;

  const [findingItemCnt, setFindingItemCnt] = useState(0); // 审计发现计数

  /** 头部表单Form列表 */
  const headerFormListRef = useRef<Array<Form>>([]);
  /** 审计发现列表 */
  const findingListRef = useRef<Array<ElementRef<typeof AuditFindingItem>>>([]);

  const getAddInitData = (): DeepPartial<AuditFindingsGroup> => ({
    auditProblemGroupId: getUUid('string') as string,
    auditProblemList: [
      {
        problemId: getUUid('string') as string,
      },
    ],
  });

  /**
   * 审计发现组列表change事件
   * @param val 变更后的审计发现组列表
   */
  const handleListChange = (val: AuditFindingsGroup[]) => {
    onChange?.(val);
  };

  const handleItemChange = (key: string, val, index: number) => {
    switch (key) {
      case 'businessProcess': {
        const newDataList = cloneDeep(value);
        newDataList[index] = { ...(newDataList?.[index] ?? {}), businessProcess: val };
        onChange?.(newDataList);
        break;
      }
      case 'auditProblemList': {
        const newDataList = cloneDeep(value);
        newDataList[index] = { ...(newDataList?.[index] ?? {}), auditProblemList: val };
        onChange?.(newDataList);
        break;
      }
      default:
        break;
    }
  };

  /**
   * 审计发现转移
   * @param fromGroupIndex 源审计发现组下标
   * @param fromItemIndex 源审计发现下标
   * @param toGroupIndex 目标审计发现组下标
   * @param toItemIndex 目标审计发现下标
   */
  const handleTransfer = (fromGroupIndex: number, fromItemIndex: number, toGroupIndex: number, toItemIndex: number) => {
    const tempValue: AuditFindingsGroup[] = cloneDeep(value);
    // 转移组下标如果大于组的数量，则移到最后一组
    if (toGroupIndex > value?.length) toGroupIndex = value?.length;
    // 转移审计发现如果大于目标组的审计发现数量，则移到该组的最后一位
    if (toItemIndex > value?.[toGroupIndex - 1]?.auditProblemList?.length) {
      toItemIndex = Number(value?.[toGroupIndex - 1]?.auditProblemList?.length) + 1 || 0;
    }
    if (toGroupIndex > 0 && toItemIndex > 0) {
      const [item] = tempValue?.[fromGroupIndex]?.auditProblemList?.splice(fromItemIndex, 1) ?? [];
      tempValue?.[toGroupIndex - 1]?.auditProblemList?.splice(toItemIndex - 1, 0, item);
      onChange?.(tempValue);
    }
  };

  const handleValidate = () => {
    let validate = true;
    headerFormListRef.current?.forEach((formRef) => {
      if (formRef) {
        const headerValidate = formRef?.validateFields();
        if (validate && !headerValidate) validate = false;
      }
    });
    findingListRef.current?.forEach((itemRef) => {
      if (itemRef) {
        const contentValidate = itemRef?.onValidate();
        if (validate && !contentValidate) validate = false;
      }
    });
    return validate;
  };

  useEffect(() => {
    let completeFindingsCnt = 0;
    let problemIndex = 0;
    value?.forEach((item) => {
      completeFindingsCnt += item?.auditProblemList?.length ?? 0;
      item?.auditProblemList?.forEach((problem) => {
        problemIndex += 1;
        problem.problemIndex = problemIndex;
      });
    });
    setFindingItemCnt(completeFindingsCnt);
  }, [value]);

  useImperativeHandle(ref, () => ({ onValidate: handleValidate }));

  const renderCardHeadSelect = (val: AuditFindingsGroup, index: number) => {
    const { businessProcess } = val ?? {};
    return (
      <Form
        className="audit-finding-group-header-form"
        ref={(formRef: Form) => {
          headerFormListRef.current[index] = formRef;
        }}
        mode={mode}
        defaultFieldsValue={{ businessProcess }}
        onFieldValueChange={(formKey, formVal) => handleItemChange(formKey, formVal, index)}
      >
        <Form.Item
          formItemKey="businessProcess"
          label="审计领域："
          rules={[
            { required: true, whitespace: true, message: '请输入审计领域：' },
            { max: NORMAL_MAX_LENGTH, message: `不允许超过${NORMAL_MAX_LENGTH}字符` },
          ]}
        >
          {({ value: businessProcessValue }) => {
            if (mode === 'edit' || businessProcessValue?.length > 0) {
              return (
                <Input
                  toFormItem
                  dispatchChange={['onInput']}
                  placeholder={`输入不超过${NORMAL_MAX_LENGTH}字符`}
                  showCount
                  maxLength={NORMAL_MAX_LENGTH}
                />
              );
            }
            return '-';
          }}
        </Form.Item>
      </Form>
    );
  };

  const renderCardContent = (val: AuditFindingsGroup, index: number) => {
    const { auditProblemList } = val ?? {};
    return (
      <AuditFindingItem
        ref={(itemRef: ElementRef<typeof AuditFindingItem>) => {
          findingListRef.current[index] = itemRef;
        }}
        riskGradeList={riskGradeList}
        value={auditProblemList}
        onChange={(changeVal) => handleItemChange('auditProblemList', changeVal, index)}
        mode={mode}
        parentGroupIndex={index}
        findingItemCnt={findingItemCnt}
        onTransfer={handleTransfer}
      />
    );
  };

  return (
    <CollapseList<DeepPartial<AuditFindingsGroup>>
      className="audit-finding-group"
      title={(val, index) => `审计发现组${index + 1}`}
      // @ts-expect-error
      defaultValue={[...Array(value?.length ?? 0).keys()]}
      expandIconPosition="end"
      multiple
      addDisable={() => findingItemCnt >= PROBLEM_LIST_MAX}
      deleteDisable={(val, index, dataList) => dataList?.length <= 1}
      addInitData={getAddInitData}
      data={value}
      keyField="auditProblemGroupId"
      mode={mode}
      onChange={handleListChange}
      renderHeaderSelect={renderCardHeadSelect}
      renderContent={renderCardContent}
      getContainer={() => document.querySelector('.project-detail-content') || document.body}
    />
  );
});

export default AuditFindingGroup;
